import codecs
import itertools
import os.path
import json
import networkx as nx
import matplotlib.pyplot as plt
from networkx.readwrite import json_graph

graph_id = 1


def make_dir(dir):
    if not os.path.exists(dir):
        os.mkdir(dir)


def generate_all_edges(node_num: int):
    ret = []
    for i in range(node_num):
        for j in range(i + 1, node_num):
            ret.append((i, j))
    return ret


def generate_all_graphs_inner(node_num: int, edge_num: int, path: str):
    global graph_id
    all_edges = generate_all_edges(node_num)
    graphs = []
    for selected_edges in itertools.combinations(all_edges, edge_num):
        new_graph = nx.Graph()
        new_graph.add_nodes_from(nx.path_graph(node_num))
        new_graph.add_edges_from(selected_edges)
        is_new_graph = True
        if len(list(nx.connected_components(new_graph))) > 1:
            is_new_graph = False
        for i in range(node_num):
            if new_graph.degree(i) == 2:
                is_new_graph = False
                break
        if is_new_graph:
            for old_graph in graphs:
                if nx.is_isomorphic(new_graph, old_graph):
                    is_new_graph = False
                    break
        if is_new_graph:
            graphs.append(new_graph)
            file_name = "./{}/{}-{}-{}.json".format(path, graph_id, len(new_graph.nodes), len(new_graph.edges))
            data = json_graph.node_link_data(new_graph)
            print(data)
            with codecs.open(file_name + ".json", "w", "utf-8") as f:
                json.dump(data, f)
            nx.draw(new_graph, with_labels=True)
            # plt.show()
            plt.savefig(file_name + ".png")
            plt.clf()
            graph_id = graph_id + 1


def generate_all_graphs(min_node_num: int, max_node_num: int):
    make_dir("./graphs")
    for node_num in range(max(2, min_node_num), max_node_num + 1):
        for edge_num in range(node_num - 1, node_num + 1):
            generate_all_graphs_inner(node_num, edge_num, "graphs")


def generate_all_trees(min_node_num: int, max_node_num: int):
    make_dir("./trees")
    for node_num in range(max(2, min_node_num), max_node_num + 1):
        generate_all_graphs_inner(node_num, node_num - 1, "trees")


def generate_all_ring_trees(min_node_num: int, max_node_num: int):
    make_dir("./ring_trees")
    for node_num in range(max(2, min_node_num), max_node_num + 1):
        generate_all_graphs_inner(node_num, node_num, "ring_trees")


generate_all_trees(2, 7)
generate_all_ring_trees(2, 7)
generate_all_graphs(2, 7)
